package ft.app.gtig.gui.timelineevent;

import com.haulmont.cuba.core.app.DataService;
import com.haulmont.cuba.core.entity.FileDescriptor;
import com.haulmont.cuba.core.global.LoadContext;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.core.global.PersistenceHelper;
import com.haulmont.cuba.gui.WindowManager;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.components.actions.BaseAction;
import com.haulmont.cuba.gui.components.actions.ItemTrackingAction;
import com.haulmont.cuba.gui.components.actions.RemoveAction;
import com.haulmont.cuba.gui.data.CollectionDatasource;
import com.haulmont.cuba.gui.data.DataSupplier;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.upload.FileUploadingAPI;
import com.haulmont.cuba.gui.xml.layout.ComponentsFactory;
import ft.app.gtig.entity.*;
import ft.app.gtig.service.QiNiuFileStorageService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;

public class TimelineEventEdit extends AbstractEditor<TimelineEvent> {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Inject
    private FileUploadingAPI fileUploadingAPI;

    @Inject
    private QiNiuFileStorageService qiNiuFileStorageService;

    @Inject
    private DataSupplier dataSupplier;
    @Inject
    private DataService dataService;
    @Inject
    private Metadata metadata;

    @Inject
    private Datasource<TimelineEvent> dsTimelineEvent;

    @Inject
    private CollectionDatasource<EventHighlight, UUID> dsEventHighlights;

    @Inject
    private CollectionDatasource<EventAgenda, UUID> dsEventAgendas;

    @Inject
    private CollectionDatasource<Person, UUID> confirmedSpeakersDs;

    @Inject
    private CollectionDatasource<Person, UUID> openingspeechDs;

    @Inject
    private CollectionDatasource<Person, UUID> keynotespeechDs;

    @Inject
    private CollectionDatasource<Video, UUID> videoDs;

    @Inject
    private ComponentsFactory componentsFactory;

    @Inject
    private FileMultiUploadField multiUploadField;

    @Inject
    private FlowBoxLayout imagesFlowBox;

    @Inject
    private Table<EventHighlight> highlightTable;

    @Inject
    private Table<EventAgenda> agendaTable;

    @Inject
    private Table<Person> confirmedSpeakersTable;

    @Inject
    private Table<Person> openingspeechTable;

    @Inject
    private Table<Person> keynotespeechTable;

    @Inject
    private Table<Video> videoTable;

    @Inject
    private Label highlightLabel;

    @Inject
    private VBoxLayout highlightPanel;

    @Inject
    private Label agendaLabel;

    @Inject
    private VBoxLayout agendaPanel;

    @Inject
    private Label personLabel;

    @Inject
    private VBoxLayout personPanel;

    @Inject
    private GridLayout gridPanel;

    @Override
    public void init(Map<String, Object> params) {

        highlightTable.addAction(new AddHighlightAction());
        highlightTable.addAction(new EditHighlightAction());
        highlightTable.addAction(new RemoveAction(highlightTable, false));

        agendaTable.addAction(new AddAgendaAction());
        agendaTable.addAction(new EditAgendaAction());
        agendaTable.addAction(new RemoveAction(agendaTable, false));

        confirmedSpeakersTable.addAction(new AddConfirmedSpeakersAction());
        confirmedSpeakersTable.addAction(new EditConfirmedSpeakersAction());
        confirmedSpeakersTable.addAction(new RemoveAction(confirmedSpeakersTable, false));

        openingspeechTable.addAction(new AddOpeningspeechAction());
        openingspeechTable.addAction(new EditOpeningspeechAction());
        openingspeechTable.addAction(new RemoveAction(openingspeechTable, false));

        keynotespeechTable.addAction(new AddKeynotespeechAction());
        keynotespeechTable.addAction(new EditKeynotespeechAction());
        keynotespeechTable.addAction(new RemoveAction(keynotespeechTable, false));

        videoTable.addAction(new AddVideoAction());
        videoTable.addAction(new EditVideoAction());
        videoTable.addAction(new RemoveAction(videoTable, false));

        multiUploadField.addQueueUploadCompleteListener(() -> {

            StringBuilder images = new StringBuilder(333);

            for (Map.Entry<UUID, String> entry : multiUploadField.getUploadsMap().entrySet()) {
                UUID fileId = entry.getKey();
                String fileName = entry.getValue();

                FileDescriptor srcFd = fileUploadingAPI.getFileDescriptor(fileId, fileName);

                FileDescriptor dstFd = dataSupplier.commit(srcFd);

                qiNiuFileStorageService.uploadFile(fileUploadingAPI.getFile(fileId), dstFd.getId().toString());

                images.append(dstFd.getId());
                images.append(",");
            }

            if (images.length() > 0) {
                getItem().setImages(images.toString());
                displayImages();
            }

            showNotification("Uploaded files: " + multiUploadField.getUploadsMap().values(), NotificationType.HUMANIZED);
            multiUploadField.clearUploads();
        });

        multiUploadField.addFileUploadErrorListener(event ->
                showNotification("File upload error", NotificationType.HUMANIZED));
    }

    @Override
    protected void postInit() {
//            if (PersistenceHelper.isNew(getItem())) {
////       dsTimelineEvent.setAllowCommit(false);
//     } else {
//       dsTimelineEvent.setAllowCommit(true);
//     }
        displayImages();
        if (!PersistenceHelper.isNew(getItem())) {
            if(getItem().getKind().getId() == 3){
                highlightLabel.setVisible(false);
                highlightPanel.setVisible(false);
                agendaLabel.setVisible(false);
                agendaPanel.setVisible(false);
                personLabel.setVisible(false);
                personPanel.setVisible(false);
                gridPanel.setVisible(false);
            }
        }
    }
//     @Override
//   protected boolean postCommit(boolean committed, boolean close){
//
//     confirmedSpeakersDs.updateItem(getItem().getConfirmedSpeakers());
//     confirmedSpeakersDs.modifyItem(getItem().getConfirmedSpeakers());
//     confirmedSpeakersDs.commit();
//     return true;
//   }

    private void displayImages() {
        imagesFlowBox.removeAll();
        if (getItem().getImages() == null) {
            return;
        }

        String[] imagesId = StringUtils.split(getItem().getImages(), ',');
        if (imagesId.length == 0) {
            return;
        }

        for (String imgId : imagesId) {
            UUID fileId = UUID.fromString(imgId);
            FileDescriptor fd = dataService.load(LoadContext.create(FileDescriptor.class).setId(fileId));
            if (fd == null || fd.isDeleted()) {
                continue;
            }

            VBoxLayout embedded = createEmbedded(fd);
            if (embedded == null) {
                continue;
            }

            imagesFlowBox.add(embedded);
        }
    }

    private VBoxLayout createEmbedded(FileDescriptor imageFile) {

        VBoxLayout vBoxLayout = componentsFactory.createComponent(VBoxLayout.class);
        vBoxLayout.setWidth(null);

        Embedded embedded = componentsFactory.createComponent(Embedded.class);

        try {
            embedded.setType(Embedded.Type.IMAGE);
            embedded.setSource(imageFile.getName(), qiNiuFileStorageService.downloadFile(imageFile));

            vBoxLayout.add(embedded);

            Button button = componentsFactory.createComponent(Button.class);
            button.setAlignment(Alignment.TOP_CENTER);
            button.setCaption("Clear");
            button.setAction(new BaseAction("hello") {
                @Override
                public void actionPerform(Component component) {
                    imagesFlowBox.remove(vBoxLayout);
//                    vBoxLayout.setVisible(false);
                    TimelineEventEdit.this.clearImage(imageFile);
                }
            });
            vBoxLayout.add(button);

            return vBoxLayout;
        } catch (IOException e) {
            log.error("createEmbedded error.", e);
            return null;
        }
    }

    private void clearImage(FileDescriptor imageFile) {
        StringBuilder images = new StringBuilder(333);
        String[] srcImages = getItem().getImages().split(",");
        for (String image : srcImages) {
            if (StringUtils.equals(image, imageFile.getId().toString())) {
                continue;
            }
            images.append(image);
            images.append(",");
        }

        getItem().setImages(images.toString());
    }

    private class AddHighlightAction extends AbstractAction {

        private AddHighlightAction() {
            super("add");
        }

        @Override
        public void actionPerform(Component component) {
            final EventHighlight eventHighlight = metadata.create(EventHighlight.class);

            eventHighlight.setTimelineEvent(dsTimelineEvent.getItem());

            Window dataEditor = openEditor("gtig$EventHighlight.edit", eventHighlight,
                    WindowManager.OpenType.DIALOG, dsEventHighlights);
            dataEditor.addCloseListener(actionId -> highlightTable.requestFocus());
        }
    }

    private class EditHighlightAction extends ItemTrackingAction {

        private EditHighlightAction() {
            super("edit");
        }

        @Override
        public void actionPerform(Component component) {

            if (dsEventHighlights.getItem() != null) {
                Window dataEditor = openEditor("gtig$EventHighlight.edit", dsEventHighlights.getItem(),
                        WindowManager.OpenType.DIALOG, dsEventHighlights);
                dataEditor.addCloseListener(actionId -> highlightTable.requestFocus());
            }
        }
    }

    private class AddAgendaAction extends AbstractAction {

        private AddAgendaAction() {
            super("add");
        }

        @Override
        public void actionPerform(Component component) {
            final EventAgenda eventAgenda = metadata.create(EventAgenda.class);

            eventAgenda.setTimelineEvent(dsTimelineEvent.getItem());

            Window dataEditor = openEditor("gtig$EventAgenda.edit", eventAgenda,
                    WindowManager.OpenType.DIALOG, dsEventAgendas);
            dataEditor.addCloseListener(actionId -> agendaTable.requestFocus());
        }
    }

    private class EditAgendaAction extends ItemTrackingAction {

        private EditAgendaAction() {
            super("edit");
        }

        @Override
        public void actionPerform(Component component) {

            if (dsEventAgendas.getItem() != null) {
                Window dataEditor = openEditor("gtig$EventAgenda.edit", dsEventAgendas.getItem(),
                        WindowManager.OpenType.DIALOG, dsEventAgendas);
                dataEditor.addCloseListener(actionId -> agendaTable.requestFocus());
            }
        }
    }

    private class AddConfirmedSpeakersAction extends AbstractAction {

        private AddConfirmedSpeakersAction() {
            super("add");
        }

        @Override
        public void actionPerform(Component component) {
            final Person confirmedSpeaker = metadata.create(Person.class);

//            confirmedSpeakers.set(dsTimelineEvent.getItem().);

            Window dataEditor = openEditor("gtig$Person.edit", confirmedSpeaker,
              WindowManager.OpenType.THIS_TAB, confirmedSpeakersDs);
            dataEditor.addCloseListener(actionId -> confirmedSpeakersTable.requestFocus());
        }
    }

    private class EditConfirmedSpeakersAction extends ItemTrackingAction {

        private EditConfirmedSpeakersAction() {
            super("edit");
        }

        @Override
        public void actionPerform(Component component) {

            if (confirmedSpeakersDs.getItem() != null) {
                Window dataEditor = openEditor("gtig$Person.edit", confirmedSpeakersDs.getItem(),
                  WindowManager.OpenType.THIS_TAB, confirmedSpeakersDs);
                dataEditor.addCloseListener(actionId -> confirmedSpeakersTable.requestFocus());
            }
        }
    }

    private class AddOpeningspeechAction extends AbstractAction {

        private AddOpeningspeechAction() {
            super("add");
        }

        @Override
        public void actionPerform(Component component) {
            final Person openingspeech = metadata.create(Person.class);

//            confirmedSpeakers.set(dsTimelineEvent.getItem().);

            Window dataEditor = openEditor("gtig$Person.edit", openingspeech,
              WindowManager.OpenType.THIS_TAB, openingspeechDs);
            dataEditor.addCloseListener(actionId -> openingspeechTable.requestFocus());
        }
    }

    private class EditOpeningspeechAction extends ItemTrackingAction {

        private EditOpeningspeechAction() {
            super("edit");
        }

        @Override
        public void actionPerform(Component component) {

            if (openingspeechDs.getItem() != null) {
                Window dataEditor = openEditor("gtig$Person.edit", openingspeechDs.getItem(),
                  WindowManager.OpenType.THIS_TAB, openingspeechDs);
                dataEditor.addCloseListener(actionId -> openingspeechTable.requestFocus());
            }
        }
    }

    private class AddKeynotespeechAction extends AbstractAction {

        private AddKeynotespeechAction() {
            super("add");
        }

        @Override
        public void actionPerform(Component component) {
            final Person keynotespeech = metadata.create(Person.class);

//            confirmedSpeakers.set(dsTimelineEvent.getItem().);

            Window dataEditor = openEditor("gtig$Person.edit", keynotespeech,
              WindowManager.OpenType.THIS_TAB, keynotespeechDs);
            dataEditor.addCloseListener(actionId -> keynotespeechTable.requestFocus());
        }
    }

    private class EditKeynotespeechAction extends ItemTrackingAction {

        private EditKeynotespeechAction() {
            super("edit");
        }

        @Override
        public void actionPerform(Component component) {

            if (keynotespeechDs.getItem() != null) {
                Window dataEditor = openEditor("gtig$Person.edit", keynotespeechDs.getItem(),
                  WindowManager.OpenType.THIS_TAB, keynotespeechDs);
                dataEditor.addCloseListener(actionId -> keynotespeechTable.requestFocus());
            }
        }
    }

    private class AddVideoAction extends AbstractAction {

        private AddVideoAction() {
            super("add");
        }

        @Override
        public void actionPerform(Component component) {
            final Video video = metadata.create(Video.class);

//            confirmedSpeakers.set(dsTimelineEvent.getItem().);

            Window dataEditor = openEditor("gtig$Video.edit", video,
              WindowManager.OpenType.THIS_TAB, videoDs);
            dataEditor.addCloseListener(actionId -> videoTable.requestFocus());
        }
    }

    private class EditVideoAction extends ItemTrackingAction {

        private EditVideoAction() {
            super("edit");
        }

        @Override
        public void actionPerform(Component component) {

            if (videoDs.getItem() != null) {
                Window dataEditor = openEditor("gtig$Person.edit", videoDs.getItem(),
                  WindowManager.OpenType.THIS_TAB, videoDs);
                dataEditor.addCloseListener(actionId -> videoTable.requestFocus());
            }
        }
    }

    public Component generateSortCell(Person entity) {
		return null;
    }
}